/* Copyright (C) 2010 Fredrique Samuels, fredriquesamuels@gmail.com */

/*
  This program is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation; either version 2 of the License, or
  (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include "template_scene.h"

namespace tri {

EntityContainer::EntityContainer(std::string id,int type,tri::entity* entity)
	:  mID(id),mType(type), mEntity(entity)
{
}

EntityContainer::~EntityContainer(){
	delete mEntity;
}

TemplateScene::TemplateScene(bool demo): tri::scene(),mEditEntity(NULL),mResetOnSceneEntry(true)
	,mDynamicAspectRatio(true), mHasInit(false){
	mDemo = demo;
	

	mExportSceneDirectory = "";
	mSaveLoadSceneDirectory = "";
	mLoadImageDirectory = tri::sys::getcwdir();

	
	if (demo){
		addNewEntity(TYPE_GLYPH,"Glyph");
		setEditEntity("Glyph");
		EntityContainer* aEditEnt = getEditEntity();
		((tri::glyph*)aEditEnt->mEntity)->setSize(5,5,0);
	}
}
TemplateScene::~TemplateScene(){}

void TemplateScene::setExportDirectory(std::string dir){
	TemplateScene::mExportSceneDirectory = dir;
}

void TemplateScene::addMaterial(std::string mat,bool override){
	std::string matName = mat;
	int count = 1;
	
	while(hasMaterial(matName) && !override){
		count++;
		matName = mat+"_"+tri::utils::getFormatString("%d",count);
	}
	mMaterialMap[matName] = matName;
	
	Material::createMaterial(matName);
	
	if (!override){
		MATERIAL_LIST_CHANGED.emit();
	}
}

bool TemplateScene::hasMaterial(std::string key){
	std::map<std::string,std::string>::iterator it;
	for ( it=mMaterialMap.begin() ; it != mMaterialMap.end(); it++ ){
		if ((*it).first == key){
			return true;
		}
	}
	return false;
}

void TemplateScene::deleteMaterial(std::string key){
	Material::deleteMaterial(key);
	mMaterialMap.erase(key);
	MATERIAL_LIST_CHANGED.emit();
}

void TemplateScene::getMaterialList(std::vector<std::string>& list){
	list.clear();
	std::map<std::string,std::string>::iterator it;
	for ( it=mMaterialMap.begin() ; it != mMaterialMap.end(); it++ ){
		list.push_back((*it).first);
	}
}


void TemplateScene::setResetOnSceneEntry(bool b){
	mResetOnSceneEntry = b;
}

void TemplateScene::on_scene_open(){
	
	tri::vector v(0, 0, 10);
	getCamera()->setPosition(&v);
	
	if(mDynamicAspectRatio){
		int w;
		int h;
		((tri::world*)this->get_parent())->getScreenSize(w,h);
		getCamera()->set_aspect_ratio((float)w/h);
	}
	
	if (!mHasInit){
		if (mDemo){
			std::string image = "opengl_3_logo.png";
			addMaterial("OPENGL_LOGO");
			tri::Material::getMaterial("OPENGL_LOGO")->setImage(image);
			
			EntityContainer* aEditEnt = getEditEntity();
			((tri::glyph*)aEditEnt->mEntity)->setImage(image);
			((tri::glyph*)aEditEnt->mEntity)->setColor(255,0,0,255);
			((tri::glyph*)aEditEnt->mEntity)->setMaterial("OPENGL_LOGO");
			
		}
		mHasInit = true;
	}
}

void TemplateScene::on_scene_close(){}

void TemplateScene::on_screen_resize(int w,int h){
	tri::scene::on_screen_resize(w,h);
	if(mDynamicAspectRatio){
		getCamera()->set_aspect_ratio((float)w/h);
	}
}

std::string TemplateScene::getQualifiedName(std::string type,std::string name){
	if(tri::utils::toUpper(type) == "GLYPH"){
		return std::string("glph")+name;
	}
	
	return "";
}

std::string TemplateScene::enumToStringType(int type){
	switch(type){
	case TYPE_GLYPH:
		return "GLYPH";
		break;
	case TYPE_CUBE:
		return "CUBE";
		break;
	case TYPE_SPHERE:
		return "SPHERE";
		break;
	}
	return "";
}

int TemplateScene::stringToEnumType(std::string str_type){
	if(str_type == "GLYPH"){
		return TYPE_GLYPH;
	}else if(str_type == "CUBE"){
		return TYPE_CUBE;
	}else if(str_type == "SPHERE"){
		return TYPE_SPHERE;
	}
	return -1;
}

void TemplateScene::addNewEntity(int type,std::string name){

	//see if the name is already in use

	std::string qualifiedName = name;
	int count = 1;
	while (entityExists(qualifiedName)){
		count++;
		qualifiedName = name +"_"+tri::utils::int2string(count);
	}

	EntityContainer* newEntity = NULL;
	switch(type){
	case TYPE_GLYPH:
		newEntity = new EntityContainer(qualifiedName,type,new tri::glyph());
		newEntity->mEntity->setName(qualifiedName);
		newEntity->mEntity->PRESSED_WS.connect(this,&TemplateScene::entitySelected);
		break;
	case TYPE_CUBE:
		newEntity = new EntityContainer(qualifiedName,type,new tri::cube());
		newEntity->mEntity->setName(qualifiedName);
		newEntity->mEntity->PRESSED_WS.connect(this,&TemplateScene::entitySelected);
		break;
	case TYPE_SPHERE:
		newEntity = new EntityContainer(qualifiedName,type,new tri::sphere());
		newEntity->mEntity->setName(qualifiedName);
		newEntity->mEntity->PRESSED_WS.connect(this,&TemplateScene::entitySelected);
		break;
	default:
		return;
	}
	
	
	if ( newEntity!=NULL ){
		tri::LOG_INFO("Creating... " + TemplateScene::enumToStringType(newEntity->mType) + " -> "+newEntity->mEntity->getName());
		mEntityMap[newEntity->mID] = newEntity;
		addEntity(newEntity->mEntity);
		setEditEntity(newEntity->mID);
	}
	
}

void TemplateScene::getEntityList(std::vector<std::string> &list){
	list.clear();
	std::map<std::string,tri::EntityContainer*>::iterator it;
	for ( it=mEntityMap.begin() ; it != mEntityMap.end(); it++ ){
		list.push_back((*it).first);
	}
}

void TemplateScene::entitySelected(tri::events::event_entity* ent){
	tri::entity* aEntity = (tri::entity*)ent;
	std::cout<<aEntity->getName()<<std::endl;
	this->setEditEntity(aEntity->getName());
}

bool TemplateScene::entityExists(std::string ent){
	std::map<std::string,tri::EntityContainer*>::iterator it;
	for ( it=mEntityMap.begin() ; it != mEntityMap.end(); it++ ){
		if (ent.compare((*it).first)==0){
			return true;
		}
	}
	return false;
}

	
void TemplateScene::exportToCPP(std::string _file){
	if (getName()== "" && _file == ""){
		return;
	}
	
	std::string file = _file;
	std::fstream file_op(file.c_str(),std::ios::out);
	tri::LOG_INFO("Exporting File ... " + file);
	//write gerated stub
	file_op<< "/***********************************"<< std::endl;
	file_op<< " * Auto-Generated by scene_builder.*"<< std::endl;
	file_op<< " * DO NOT EDIT.                    *"<<std::endl;
	file_op<< " ***********************************/"<<std::endl;
	
	//write macros
	file_op << std::endl;
	file_op << "#ifndef _GENERATED_SCENE_"<<tri::utils::toUpper(getName())<<"_H_"<<std::endl;
	file_op << "#define _GENERATED_SCENE_"<<tri::utils::toUpper(getName())<<"_H_"<<std::endl;
	
	file_op << std::endl;
	file_op << std::endl;
	
	//write includes
	file_op << "#include <triangulum.h>"<<std::endl;
	
	file_op << std::endl;
	file_op << std::endl;
	
	
	file_op << "class " <<getName() << " :  public tri::scene { "<<std::endl;
	file_op << "public:"<<std::endl;
	
	//contructor
	file_op << "    "<<getName()<< "() : tri::scene() { "<<std::endl;
	file_op << "        setup();"<<std::endl;
	file_op << "    }"<<std::endl<<std::endl;
	
	//destructor
	file_op << "    virtual ~"<<getName()<< "() { "<<std::endl;
	file_op << "    }"<<std::endl<<std::endl;
	
	//virtual methods
	file_op << "    virtual void on_scene_open() { "<<std::endl;
	file_op << "        int w;"<<std::endl;
	file_op << "        int h;"<<std::endl;
	file_op << "        ((tri::world*)this->get_parent())->getScreenSize(w,h);"<<std::endl;
	file_op << "        getCamera()->set_aspect_ratio((float)w/h);"<<std::endl;
	if (mResetOnSceneEntry){
		file_op << "        setup();"<<std::endl;
	}
	file_op << "    }"<<std::endl<<std::endl;
	
	file_op << "    virtual void on_scene_close() { "<<std::endl;
	file_op << "    }"<<std::endl<<std::endl; 
	
	if(mDynamicAspectRatio){
		file_op << "    virtual void on_screen_resize(int w, int h) { "<<std::endl;
		file_op << "        getCamera()->set_aspect_ratio((float)w/h);"<<std::endl;
		file_op << "    }"<<std::endl<<std::endl;
	}
	
	file_op << "    virtual void update() { "<<std::endl;
	file_op << "        tri::scene::update();"<<std::endl;
	file_op << "    }"<<std::endl<<std::endl;
	//contructor
	file_op << "    void setup() { "<<std::endl;
	exportNodes(file_op);
	exportEntityAttributes(file_op);
	file_op << "    }"<<std::endl<<std::endl;
	
	exportAttributes(file_op);
	
	file_op << "};"<<std::endl;
	file_op << std::endl;
	file_op <<"#endif"<<std::endl;
	file_op.close();
}

void TemplateScene::exportAttributes(std::fstream& file_op){
	std::map<std::string,tri::EntityContainer*>::iterator it;
	for ( it=mEntityMap.begin() ; it != mEntityMap.end(); it++ ){
		switch((*it).second->mType){
		case TYPE_GLYPH:
			file_op<<"    tri::glyph "<<(*it).first<<";"<<std::endl;
			break;
		case TYPE_SPHERE:
			file_op<<"    tri::sphere "<<(*it).first<<";"<<std::endl;
			break;
		case TYPE_CUBE:
			file_op<<"    tri::cube "<<(*it).first<<";"<<std::endl;
		}
	}
	file_op<<std::endl;
}

EntityContainer* TemplateScene::getContainer(tri::entity* ent){
	std::map<std::string,tri::EntityContainer*>::iterator it;
	for ( it=mEntityMap.begin() ; it != mEntityMap.end(); it++ ){
		if ((*it).second->mEntity == ent){
			return (*it).second;
		}
	}
	return NULL;
}

EntityContainer* TemplateScene::getContainer(std::string ent){
	std::map<std::string,tri::EntityContainer*>::iterator it;
	for ( it=mEntityMap.begin() ; it != mEntityMap.end(); it++ ){
		if ((*it).second->mEntity->getName() == ent){
			return (*it).second;
		}
	}
	return NULL;
}

void TemplateScene::exportNodes(std::fstream& file_op){
	std::map<std::string,tri::EntityContainer*>::iterator it;
	for ( it=mEntityMap.begin() ; it != mEntityMap.end(); it++ ){
		tri::entity* node = (tri::entity*)(*it).second->mEntity->getRootNode();
		if (node == NULL){
		}else if(node == this){
			file_op<<"        addEntity(&"<<(*it).first<<");"<<std::endl;
		}else{
			tri::EntityContainer* container = getContainer(node);
			if ( container != NULL ){
				file_op<<"        "<<container->mID<<".addEntity(&"<<(*it).first<<");"<<std::endl;
			}
		}
	}
	file_op<<std::endl;
}

void TemplateScene::exportEntityAttributes(std::fstream& file_op){
	
	tri::world* parent = (tri::world*)this->get_parent();
	if( parent != NULL ){
		tri::vector cam_pos = parent->getCamera()->getPosition();
		tri::vector cam_rot = parent->getCamera()->getRotation();
		float viewAngle = parent->getCamera()->getViewAngle();
		
		file_op<<"        getCamera()->setPosition("<<cam_pos.x<<","<<cam_pos.y<<","<<cam_pos.z<<");"<<std::endl;
		file_op<<"        getCamera()->setRotation("<<cam_rot.x<<","<<cam_rot.y<<","<<cam_rot.z<<");"<<std::endl;
		file_op<<"        getCamera()->set_view_angle("<<viewAngle<<");"<<std::endl;
		file_op<<std::endl;
	}
	
	
	
	std::map<std::string,tri::EntityContainer*>::iterator it;
    for ( it=mEntityMap.begin() ; it != mEntityMap.end(); it++ ){
		tri::vector pos = (*it).second->mEntity->getPosition();
		tri::vector rot = (*it).second->mEntity->getRotation();
		tri::vector size = (*it).second->mEntity->getSize();
		bool visible = (*it).second->mEntity->isVisible();
		std::string name = (*it).second->mEntity->getName();
		
		file_op<<"        "<<(*it).first<<".setPosition("<<pos.x<<","<<pos.y<<","<<pos.z<<");"<<std::endl;
		file_op<<"        "<<(*it).first<<".setRotation("<<rot.x<<","<<rot.y<<","<<rot.z<<");"<<std::endl;
		file_op<<"        "<<(*it).first<<".setSize("<<size.x<<","<<size.y<<","<<size.z<<");"<<std::endl;
		file_op<<"        "<<(*it).first<<".setVisible("<<visible<<");"<<std::endl;
		file_op<<"        "<<(*it).first<<".setName(\""<<name<<"\");"<<std::endl;
		
//		switch((*it).second->mType){
//		case TYPE_GLYPH:
//		case TYPE_CUBE:
//		case TYPE_SPHERE:
//			std::string image = ((tri::TexturedEntity*)((*it).second->mEntity))->getImage();
//			if (image != ""){
//				file_op<<"        "<<(*it).first<<".setImage(\""<<image<<"\");"<<std::endl;
//			}
//			tri::graphics::RGBA color = ((tri::ColoredEntity*)((*it).second->mEntity))->getColorAsRGBA();
//			file_op<<"        "<<(*it).first<<".setColor("<<color.red<<","<<color.green<<","<<color.blue<<","<<color.alpha<<");"<<std::endl;
//			break;
//		}
		
		file_op<<std::endl;
	}
	file_op<<std::endl;
}

void TemplateScene::connectEntity(std::string parent,std::string child){
	if(!entityExists(parent) || ! entityExists(child)){
		return;
	}
	tri::LOG_INFO("Connecting ... " + parent +" -> "+ child );
	mEntityMap[parent]->mEntity->addEntity(mEntityMap[child]->mEntity);
	setEditEntity(mEntityMap[child]->mID);
}

void TemplateScene::setEditEntity(std::string name){
	if (entityExists(name)){
		if (mEditEntity != mEntityMap[name]){
			mEditEntity = mEntityMap[name];
			EDIT_ENTITY_CHANGED.emit();
		}
	}
}

EntityContainer* TemplateScene::getEditEntity(){
	return mEditEntity;
}

void TemplateScene::setDynamicAspectRatio(bool b){
	mDynamicAspectRatio = b;
}

void TemplateScene::setSaveLoadDirectory(std::string dir){
	mSaveLoadSceneDirectory = dir;
}

void TemplateScene::setLoadImageDirectory(std::string dir){
	if (tri::sys::isdir(dir)){
		mLoadImageDirectory = dir;
	}
}

std::string TemplateScene::getLoadImageDirectory(){
	return mLoadImageDirectory;
}

void TemplateScene::writeString(std::fstream& binary_file,std::string aName){
	int NAME_SIZE = aName.size();
	binary_file.write(reinterpret_cast<char *>(&NAME_SIZE),sizeof(int));
	if (NAME_SIZE > 0){
		binary_file.write(aName.c_str(),sizeof(char)*NAME_SIZE);
	}
}

std::string TemplateScene::readString(std::fstream& binary_file){
	int NAME_SIZE = 0;
	std::string type = "";
	binary_file.read(reinterpret_cast<char *>(&NAME_SIZE),sizeof(int));
	if (NAME_SIZE > 0){
		char typebuf[300];
		binary_file.read(typebuf,sizeof(char)*NAME_SIZE);
		type.append(typebuf,NAME_SIZE);
	}
	return type;
}

void TemplateScene::writeInt(std::fstream& binary_file,int value){
	binary_file.write(reinterpret_cast<char *>(&value),sizeof(int));
}

int TemplateScene::readInt(std::fstream& binary_file){
	int value;
	binary_file.read(reinterpret_cast<char *>(&value),sizeof(int));
	return value;
}

void TemplateScene::writeFloat(std::fstream& binary_file,float value){
	binary_file.write(reinterpret_cast<char *>(&value),sizeof(float));
}

float TemplateScene::readFloat(std::fstream& binary_file){
	float value;
	binary_file.read(reinterpret_cast<char *>(&value),sizeof(float));
	return value;
}

void TemplateScene::writeVector(std::fstream& binary_file, tri::vector v){
	writeFloat(binary_file,v.x);
	writeFloat(binary_file,v.y);
	writeFloat(binary_file,v.z);
}

tri::vector TemplateScene::readVector(std::fstream& binary_file){
	tri::vector v;
	v.x = readFloat(binary_file);
	v.y = readFloat(binary_file);
	v.z = readFloat(binary_file);
	return v;
}

void TemplateScene::writeColor(std::fstream& binary_file, tri::graphics::RGBA c){
	writeInt(binary_file,c.red);
	writeInt(binary_file,c.green);
	writeInt(binary_file,c.blue);
	writeInt(binary_file,c.alpha);
}

tri::graphics::RGBA TemplateScene::readColor(std::fstream& binary_file){
	int r = readInt(binary_file);
	int g = readInt(binary_file);
	int b = readInt(binary_file);
	int a = readInt(binary_file);
	tri::graphics::RGBA c(r,g,b,a);
	return c;
}

void TemplateScene::writeHeaderChunk(std::fstream& binary_file,TemplateScene* scene){
	writeInt(binary_file,HEADER_CHUNK);
	int chunk_size = 0;
	std::string aName =  scene->getName();
	chunk_size+=sizeof(char)*aName.size();
	chunk_size+=sizeof(int);
	writeInt(binary_file,chunk_size);
	writeString(binary_file,aName);
	
}

void TemplateScene::writeCameraChunk(std::fstream& binary_file,TemplateScene* scene){
	writeInt(binary_file,CAMERA_CHUNK);
	int chunk_size = 0;
	
	chunk_size+=sizeof(float)*7;
	writeInt(binary_file,chunk_size);

	tri::vector cam_pos = scene->getCamera()->getPosition();
	writeVector(binary_file,cam_pos);
	tri::vector cam_rot = scene->getCamera()->getRotation();
	writeVector(binary_file,cam_rot);
	writeFloat(binary_file,scene->getCamera()->getViewAngle());
}

void TemplateScene::writeEndChunk(std::fstream& binary_file,TemplateScene* scene){
	writeInt(binary_file,END_CHUNK);
	int chunk_size = 0;
	writeInt(binary_file,chunk_size);
}

void TemplateScene::writeMaterialChunk(std::fstream& binary_file,TemplateScene* scene){
	
	int chunk_size = 0;
	{
		
		std::map<std::string,std::string>::iterator it;
		for ( it=scene->mMaterialMap.begin() ; it != scene->mMaterialMap.end(); it++ ){
			writeInt(binary_file,MATERIAL_CHUNK);
			
			std::string image = tri::Material::getMaterial((*it).first)->getImage();
			if (scene->mLoadImageDirectory!="" && tri::utils::startswith(image,scene->mLoadImageDirectory) && image !=""){
				image = image.substr(scene->mLoadImageDirectory.size(),image.size()-scene->mLoadImageDirectory.size());
			}
			
			chunk_size = 0;

			chunk_size+=sizeof(int);
			chunk_size+=sizeof(char)*(*it).first.size();
			
			chunk_size+=sizeof(int);
			chunk_size+=sizeof(char)*image.size();
			chunk_size+=sizeof(int)*4;
			
			writeInt(binary_file,chunk_size);
			writeString(binary_file,(*it).first);
			writeString(binary_file,image);
			writeColor(binary_file,tri::Material::getMaterial((*it).first)->getColorAsRGBA());
		}
	}
		
}

void TemplateScene::writeEntityChunk(std::fstream& binary_file,TemplateScene* scene){
	//ENTITY_CHUNK 
	tri::entity* ent = NULL;
	int chunk_size = 0;
	std::map<std::string,tri::EntityContainer*>::iterator it;
	for ( it=scene->mEntityMap.begin() ; it != scene->mEntityMap.end(); it++ ){
		ent = (*it).second->mEntity;
		chunk_size = 0;
		chunk_size+=sizeof(int); // entity type
		chunk_size+=sizeof(int); // name size
		chunk_size+=sizeof(char)*(*it).first.size(); // entity name
		chunk_size+=sizeof(float)*3*4; // 4 vectors  pos,rot,size,scale

		std::string image;		
		image = ent->getImage();
		chunk_size+=sizeof(int); // image size
		chunk_size+=sizeof(char)*image.size(); // image
	
		chunk_size+=sizeof(int)*4; // image
//		
		image  = ent->getMaterial();
		chunk_size+=sizeof(int); // material size
		chunk_size+=sizeof(char)*image.size(); // material
		
		writeInt(binary_file,ENTITY_CHUNK);//chunk type
		writeInt(binary_file,chunk_size); //chunk size
		
		writeInt(binary_file,(*it).second->mType); // entity type
		
		writeString(binary_file,(*it).first); // name
		
		
		tri::vector pos = ent->getPosition(); 
		writeVector(binary_file,pos);
		tri::vector rot = ent->getRotation();
		writeVector(binary_file,rot);
		tri::vector size = ent->getSize();
		writeVector(binary_file,size);
		tri::vector scale = ent->getScale();
		writeVector(binary_file,scale);
	
		writeColor(binary_file,ent->getColorAsRGBA());
		writeString(binary_file,ent->getImage());
		writeString(binary_file,ent->getMaterial());
	}
}


void TemplateScene::_save(TemplateScene* scene ,std::string file){
	if (scene==NULL){
		return;
	}
	if (scene->getName() == "" ){
		return;
	}
	
	std::fstream binary_file(file.c_str(),std::ios::out|std::ios::binary);
	tri::LOG_INFO("Saving File ... " + file);
	
	writeHeaderChunk(binary_file,scene);
	writeCameraChunk(binary_file,scene);
	writeEntityChunk(binary_file,scene);
	writeMaterialChunk(binary_file,scene);
	writeEndChunk(binary_file,scene);
	binary_file.close();
}

TemplateScene* TemplateScene::_load(std::string file){
	TemplateScene* retScene = NULL;
	if (!tri::sys::isfile(file)) {
		std::string msg = "File does not exists: ";
		LOG_WARNING(msg+file);
		return NULL;
	}
	
	std::fstream binary_file(file.c_str(),std::ios::in|std::ios::binary);
	
	retScene = new TemplateScene();
	int chunk_header = 0;
	int chunk_size = 0;
	while(!binary_file.eof()){
		chunk_header = readInt(binary_file);
		chunk_size = readInt(binary_file);	
		if (chunk_header == HEADER_CHUNK){
			std::string name = readString(binary_file);
			if (name!=""){
				retScene->setName(name);
			}
		}else if (chunk_header == CAMERA_CHUNK){
			tri::vector cam_pos = readVector(binary_file);
			tri::vector cam_rot = readVector(binary_file);
			float viewAngle = readFloat(binary_file);
			
			retScene->getCamera()->setPosition(cam_pos);
			retScene->getCamera()->setRotation(cam_rot);
			retScene->getCamera()->set_view_angle(viewAngle);
		
		}else if (chunk_header == ENTITY_CHUNK){

			int mType = readInt(binary_file);
			std::string ent_name = readString(binary_file);
			
			tri::vector pos = readVector(binary_file);
			tri::vector rot = readVector(binary_file);
			tri::vector size = readVector(binary_file);
			tri::vector scale = readVector(binary_file);
			
			tri::graphics::RGBA color = readColor(binary_file);
			std::string ent_image = readString(binary_file);
			std::string ent_mat = readString(binary_file);
			
			retScene->addNewEntity(mType,ent_name);
			retScene->getContainer(ent_name)->mEntity->setPosition(pos);
			retScene->getContainer(ent_name)->mEntity->setRotation(rot);
			retScene->getContainer(ent_name)->mEntity->setSize(size);
			retScene->getContainer(ent_name)->mEntity->setScale(scale);

			retScene->getContainer(ent_name)->mEntity->setColor(color);
			retScene->getContainer(ent_name)->mEntity->setImage(ent_image);
			retScene->getContainer(ent_name)->mEntity->setMaterial(ent_mat);

			
		}else if (chunk_header == MATERIAL_CHUNK){
			std::string matName = readString(binary_file);
			std::string imRelPath = readString(binary_file);
			tri::graphics::RGBA color = readColor(binary_file);
			
			retScene->addMaterial(matName,true);
			tri::Material::getMaterial(matName)->setImage(imRelPath);
			tri::Material::getMaterial(matName)->setColor(color);
			
		}else if (chunk_header == END_CHUNK){
			break;
		}else{
			binary_file.seekg(chunk_size,std::ios::cur);
		};
		
		chunk_header = 0;
		chunk_size = 0;
	}
	binary_file.close();
	return retScene;
}


void TemplateScene::save(TemplateScene* scene,std::string file){
	_save(scene,file);
	return;
//	TODO implment node chunk
//	int NODE_CHUNK = 2000;
//	writeInt(binary_file,NODE_CHUNK);
//	writeInt(binary_file,scene->mEntityMap.size());
//	
//	{
//		std::map<std::string,tri::EntityContainer*>::iterator it;
//		for ( it=scene->mEntityMap.begin() ; it != scene->mEntityMap.end(); it++ ){
//			tri::entity* node = (tri::entity*)(*it).second->mEntity->getRootNode();
//			int NodeType = 0;
//			if (node == NULL){
//			}else if(node == scene){
//				writeInt(binary_file,0);
//				writeString(binary_file,(*it).first);
//				
//			}else{
//				tri::EntityContainer* container = scene->getContainer(node);
//				if ( container != NULL ){
//					writeInt(binary_file,1);
//					writeString(binary_file,container->mID);
//					writeString(binary_file,(*it).first);
//				}
//			}
//		}
//	}
	
	
}

TemplateScene* TemplateScene::load(std::string file){
	return _load(file);
}

}
